<template>
  <Dialog :title="dialogTitle" v-model="dialogVisible" style="width: 65%">
    <el-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      label-width="100px"
      v-loading="formLoading"
    >
      <el-form-item label="素材">
        <el-button type="primary" plain @click="openForm(0)">
          <Icon icon="ep:upload" class="mr-5px"/>
          上传素材
        </el-button>
        <div v-if="formData.materialType===2" style="width: 300px;height: 200px">
          <video style="width: 300px;height: 200px" controls  crossorigin="anonymous">
              <source :src="formData.materialUrl" type="video/mp4"/>
          </video>
        </div>
      </el-form-item>
      <el-form-item label="封面">
        <el-button type="primary" plain @click="openForm(1)">
          <Icon icon="ep:upload" class="mr-5px"/>
          上传封面
        </el-button>
        <div style="width: 300px;height: 200px">
          <img :src="formData.coverImage" style="width: 300px;height: 200px"/>
        </div>
      </el-form-item>
      <el-form-item label="素材名称" prop="name">
        <el-input v-model="formData.name" placeholder="请输入素材名称"/>
      </el-form-item>
      <el-form-item label="素材类型" prop="materialType">
        <el-select
          v-model="formData.materialType"
          placeholder="请选择素材类型"
          disabled
          class="!w-240px"
        >
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE.MATERIAL_TYPE)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="分类" prop="categoryId">
        <el-tree-select
          v-model="formData.categoryId"
          :data="categoryTree"
          :props="defaultProps"
          check-strictly
          default-expand-all
          placeholder="请选择分类"
          value-key="categoryId"
        />
      </el-form-item>
      <el-form-item label="素材大小" prop="size">
        <el-input v-model="formData.size" placeholder="请输入素材大小，单位字节" v-show="false"/>
        <el-input disabled v-model="formData.sizeVal"/>
      </el-form-item>
      <el-form-item label="素材存储地址" prop="materialUrl">
        <el-input v-model="formData.materialUrl" placeholder="请输入素材存储地址" disabled/>
      </el-form-item>
      <el-form-item label="播放地址" prop="viewUrl">
        <el-input v-model="formData.viewUrl" placeholder="请输入视频、音频、文档文件加工后存储地址"
                  disabled/>
      </el-form-item>
      <el-form-item label="加工状态" prop="workStatus">
        <el-select
          v-model="formData.workStatus"
          placeholder="请选择加工状态"
          disabled
          class="!w-240px"
        >
          <el-option
            v-for="dict in getIntDictOptions(DICT_TYPE.WORK_STATUS)"
            :key="dict.value"
            :label="dict.label"
            :value="dict.value"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="加工失败信息" prop="workErrorInfo">
        <el-input v-model="formData.workErrorInfo"
                  placeholder="请输入加工失败信息，多于2048的只保留前面的部分" disabled/>
      </el-form-item>
      <el-form-item label="描述" prop="description">
        <Editor v-model="formData.description" height="150px"/>
      </el-form-item>
      <el-form-item label="时长" prop="videoDuration">
        <el-input v-model="formData.videoDuration" placeholder="请输入视频/音频 时长" disabled/>
      </el-form-item>
      <div v-if="formData.materialType == 2" style="width: 50%;height: 200px;display:none">
        <video ref="videoEl" @loadedmetadata="handleLoadedMetadata" :src="formData.materialUrl"
               controls style="width:200px;height:300px;"  crossorigin="anonymous"></video>
        <img :src="imageName" style="width:200px;height:300px;"/>
        <canvas ref="canvasR" style="width:200px;height:300px;"></canvas>
      </div>
    </el-form>
    <template #footer>
      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
      <el-button @click="dialogVisible = false">取 消</el-button>
    </template>
    <FileForm ref="fileRef" @success="getFileInfo"/>
  </Dialog>
</template>
<script setup lang="ts">
import {MaterialApi, MaterialVO} from '@/api/course/material'
import FileForm from './FileForm.vue'
import {DICT_TYPE, getIntDictOptions} from "@/utils/dict";
import {upload2} from "@/api/infra/file";
import {VideoPlayer} from "@videojs-player/vue";
import {CategoryApi} from "@/api/course/category";
import {defaultProps, handleTree} from "@/utils/tree";
import * as DeptApi from "@/api/system/dept";

/** 知识库-素材 表单 */
defineOptions({name: 'MaterialForm'})
const videoEl = ref();
const imageName = ref();
const canvasR = ref();
let timeOut1 = null;
let timeOut2 = null;
// 0 素材 1 封面
const uploadType = ref(0)
const initParentOptions = ref([{id:0,name:'顶级'}])
const parentOptions = ref([])
const categoryTree = ref() // 树形结构
const handleLoadedMetadata = () => {
  // 获取视频总时长
  const duration = videoEl.value.duration;
  formData.value.videoDuration = duration;
  canvasR.value.width = videoEl.value.videoWidth
  canvasR.value.height = videoEl.value.videoHeight
  timeOut1 = setTimeout(function () {
    canvasR.value.getContext('2d').drawImage(videoEl.value, 0, 0, canvasR.value.width, canvasR.value.height)
    //captureFirstFrame();
    timeOut2 = setTimeout(function () {
      getImgUrl();
    }, 3000);
  }, 4000)
};

async function getImgUrl() {
  imageName.value = canvasR.value.toDataURL('image/png');
  const fineName = (formData.value.name+"").split(".")[0]
  upload2({name:fineName+".jpg",path:"2024/"+fineName+".jpg",base64:imageName.value}).then((res)=>{
    formData.value.coverImage = res.data
    console.log(res)
  }).finally(()=>{
    if(timeOut1!=null){
      timeOut1=null;
    }
    if(timeOut2!=null){
      timeOut2=null;
    }
  })

  /*
  const img = new Image();
  img.src =imageName.value;
  img.style.width = '300px'; // 可以设置图片的显示大小
  img.style.height = '200px';
  // 创建一个链接元素用于下载
  const link = document.createElement('a');
  link.href = img.src;
  link.download = 'canvas-image.png';
  link.click();*/
}


const {t} = useI18n() // 国际化
const message = useMessage() // 消息弹窗
function getFileInfo(uf) {
  if(uploadType.value===0){
    formData.value.name = uf.name
    formData.value.size = uf.size
    const fileSize = formattedFileSize(uf.size);
    formData.value.sizeVal = fileSize;
    formData.value.materialUrl = uf.response.data
    formData.value.viewUrl = uf.response.data
    const materialType = getMaterialType(uf.name);
    formData.value.materialType = materialType;
    if (materialType === 2) {
      // 确保视频元素已挂载
      if (videoEl.value) {
        videoEl.value.load(); // 重新加载视频来触发loadedmetadata事件
        videoEl.value.addEventListener('loadeddata', captureFirstFrame);
      }
    }
  }else{
    formData.value.coverImage = uf.response.data
  }
  console.log(uf)
}
const coverImage = ref(null);
function captureFirstFrame() {
  const ctx = canvasR.value.getContext('2d');
  canvasR.value.width = videoEl.value.videoWidth;
  canvasR.value.height = videoEl.value.videoHeight;
  ctx.drawImage(videoEl.value, 0, 0, canvasR.value.width, canvasR.value.height);
  coverImage.value = canvasR.value.toDataURL('image/png');
}
function formattedFileSize(byte) {
  const units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
  const index = Math.floor(Math.log(byte) / Math.log(1024));
  return (byte / Math.pow(1024, index)).toFixed(2) + units[index];
}

function getMaterialType(name) {
  const filename = name.toString().toLowerCase();

  if (filename.endsWith(".ppt") || filename.endsWith(".pptx")) {
    return 1;
  }
  const videoExtensions = /\.(mp4|avi|mpg|mpeg|wmv|mov|flv|webm)$/i;
  if (videoExtensions.test(filename)) {
    return 2;
  }
  const audioExtensions = /\.(mp3|wav|ogg|flac)$/i;
  if (audioExtensions.test(filename)) {
    return 3;
  }
  const imageRegex = /\.(jpg|jpeg|png|gif|webp)$/i;
  if (imageRegex.test(filename)) {
    return 4;
  }
  if (name.endsWith(".doc") || name.endsWith(".docx")) {
    return 5;
  }
  if (name.endsWith(".xlx") || name.endsWith(".xlsx")) {
    return 6;
  }
  if (name.endsWith(".txt")) {
    return 7;
  }
  if (name.endsWith(".pdf")) {
    return 8;
  }
  return 9;
}

const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中：1）修改时的数据加载；2）提交的按钮禁用
const formType = ref('') // 表单的类型：create - 新增；update - 修改
const formData = ref({
  id: undefined,
  name: undefined,
  materialType: undefined,
  parentId: undefined,
  size: undefined,
  sizeVal: undefined,
  materialUrl: undefined,
  viewUrl: undefined,
  workStatus: undefined,
  workErrorInfo: undefined,
  version: undefined,
  deptId: undefined,
  description: undefined,
  videoDuration: undefined,
  coverImage:undefined,
  categoryId:0,
})
const formRules = reactive({
  name: [{required: true, message: '素材名称不能为空', trigger: 'blur'}],
  materialType: [{
    required: true,
    message: '素材类型 0 文件夹，1 ppt，2 视频，3 音频，4 图片，5 word， 6 excel， 7 txt， 8 pdf不能为空',
    trigger: 'change'
  }],
})

const fileRef = ref()
const openForm = (type) => {
  uploadType.value = type;
  fileRef.value.open()
}
const formRef = ref() // 表单 Ref

/** 打开弹窗 */
const open = async (type: string, id?: number) => {
  dialogVisible.value = true
  dialogTitle.value = t('action.' + type)
  formType.value = type
  resetForm()
  await getTree()
  parentOptions.value = await  CategoryApi.list()
  let newOptions = [...new Set([...initParentOptions.value, ...parentOptions.value])];
  parentOptions.value = newOptions;
  // 修改时，设置数据
  if (id) {
    formLoading.value = true
    try {
      formData.value = await MaterialApi.getMaterial(id)
    } finally {
      formLoading.value = false
    }
  }
}

const getTree = async () => {
  categoryTree.value = []
  const data = await CategoryApi.list()
  let category: Tree = { id: 0, name: '未分类', children: [] }
  category.children = handleTree(data)
  categoryTree.value.push(category)
}
defineExpose({open}) // 提供 open 方法，用于打开弹窗

/** 提交表单 */
const emit = defineEmits(['success']) // 定义 success 事件，用于操作成功后的回调
const submitForm = async () => {
  // 校验表单
  await formRef.value.validate()
  // 提交请求
  formLoading.value = true
  try {
    const data = formData.value as unknown as MaterialVO
    if (formType.value === 'create') {
      await MaterialApi.createMaterial(data)
      message.success(t('common.createSuccess'))
    } else {
      await MaterialApi.updateMaterial(data)
      message.success(t('common.updateSuccess'))
    }
    dialogVisible.value = false
    // 发送操作成功的事件
    emit('success')
  } finally {
    formLoading.value = false
  }
}

/** 重置表单 */
const resetForm = () => {
  formData.value = {
    id: undefined,
    name: undefined,
    materialType: undefined,
    parentId: undefined,
    size: undefined,
    sizeVal: undefined,
    materialUrl: undefined,
    viewUrl: undefined,
    workStatus: undefined,
    workErrorInfo: undefined,
    version: undefined,
    deptId: undefined,
    description: undefined,
    videoDuration: undefined,
    coverImage:undefined,
    categoryId:0,
  }
  formRef.value?.resetFields()
}
</script>
